
require("Scripts/Common/Utility")
require("Scripts/Common/Class")
require("Scripts/UISystem/EventTypes")

UISystem = Class()

function UISystem:Ctor()
	-- 窗口大小
	self._window_width = 0
	self._window_height = 0

	-- UI系统的层，层的顺序是固定不变的
	self.layers = {}

	-- 记录当前鼠标的位置
	self._mouse_x = 0
	self._mouse_y = 0

	self._wfc = nil		-- 鼠标滚轮焦点
	self._mfc = nil		-- 移动焦点控件
	self._mfd = nil		-- 移动焦点对话框
	
	self._sfc = nil		-- 选中焦点控件
	self._sl = false	-- 是否锁定焦点控件
	self._draging = false -- 是否正在拖拽焦点控件
end

-- 添加一个层
function UISystem:AddLayer(layer)
	-- 将层插入到layers首部
	table.insert(self.layers, 1, layer)
	-- 将show插入到尾部
	Sail_UISystem:AddLayer(layer._show)
	-- 设置层的宽高
	layer:SetWidth(self._window_width)
	layer:SetHeight(self._window_height)
end

-- 处理鼠标移动事件
function UISystem:HandleMouseMoved(x, y)
	-- 计算偏移值
	local delta_x = x - self._mouse_x
	local delta_y = y - self._mouse_y
	-- 记录当前的鼠标位置
	self._mouse_x = x
	self._mouse_y = y

	-- 检查是否锁定控件
	if self._sl then
		-- 检查是否正在拖拽
		if self._draging == false then
			-- 发送开始拖拽事件
			self._sfc:DispatchEvent({ type = EventTypes.DRAGBEGIN, target = self._sfc, delta_x = delta_x, delta_y = delta_y, x = x, y = y })
			-- 标记正在拖拽
			self._draging = true
		end
		-- 发送拖拽事件
		self._sfc:DispatchEvent({ type = EventTypes.DRAG, target = self._sfc, delta_x = delta_x, delta_y = delta_y, x = x, y = y })
		return true
	end

	-- 更新移动焦点控件
	return self:UpdateMoveFocus(x, y)
end

-- 处理鼠标左键按下事件
function UISystem:HandleLButtonDown(x, y)
	-- 更新移动焦点控件
	self:UpdateMoveFocus(x, y)
	
	-- 如果有移动焦点控件
	if self._mfc then
		-- 则向控件发送鼠标左键点击事件
		self._mfc:DispatchEvent({type = EventTypes.LBUTTONDOWN, target = self._mfc, x = x, y = y })
		-- 如果当前的选中焦点控件为空
		if self._sfc == nil then
			-- 将移动焦点控件设置为选中焦点控件
			self._sfc = self._mfc
			-- 向选中焦点控件发送获得焦点事件
			self._sfc:DispatchEvent({type = EventTypes.FOCUSIN, target = self._sfc, x = x, y = y})
		-- 如果当前有选中焦点，并且不是当前的移动焦点控件
		elseif self._mfc ~= self._sfc then
			-- 向选中焦点控件发送失去焦点事件
			self._sfc:DispatchEvent({type = EventTypes.FOCUSOUT, target = self._sfc, x = x, y = y})
			-- 将移动焦点控件设置为选中焦点控件
			self._sfc = self._mfc
			-- 向选中焦点控件发送获得焦点事件
			self._sfc:DispatchEvent({type = EventTypes.FOCUSIN, target = self._sfc, x = x, y = y})	
		end
		-- 将移动焦点控件所在的对话框设置到层的顶端
		self._mfd._parent:MoveToTop(self._mfd)
		-- 标记锁定焦点控件
		self._sl = true
		return true
	-- 如果没有移动焦点控件
	else
		-- 如果当前有选中焦点控件
		if self._sfc then
			-- 向选中焦点控件发送失去焦点事件
			self._sfc:DispatchEvent({type = EventTypes.FOCUSOUT, target = self._sfc, x = x, y = y})
			-- 将选中焦点设置为空
			self._sfc = nil
			-- 标记为不锁定焦点控件
			self._sl = false
		end
	end
	return false
end

-- 处理鼠标左键弹起事件
function UISystem:HandleLButtonUp(x, y)
	-- 如果当前没有锁定选中焦点控件，则直接返回
	if (self._sl == false) then return false end
	-- 向选中焦点控件发送鼠标弹起事件
	self._sfc:DispatchEvent({type = EventTypes.LBUTTONUP, target = self._sfc, x = x, y = y})
	-- 标记为不锁定焦点控件
	self._sl = false
	-- 如果当前正在拖拽
	if self._draging == true then
		-- 向选中焦点控件发送拖拽结束事件
		self._sfc:DispatchEvent({type = EventTypes.DRAGEND, target = self._sfc, x = x, y = y})
		-- 标记为不是正在拖拽
		self._draging = false
	end
	-- 更新移动焦点控件
	return self:UpdateMoveFocus(x, y)
end

function UISystem:HandleMButtonDown(x, y)
	return false
end

function UISystem:HandleMButtonUp(x, y)
	return false
end

function UISystem:HandleRButtonDown(x, y)
	-- 更新移动焦点控件
	self:UpdateMoveFocus(x, y)
	-- 如果有移动焦点控件
	if self._mfc then
		-- 则向控件发送鼠标左键点击事件
		self._mfc:DispatchEvent({type = EventTypes.RBUTTONDOWN, target = self._mfc, x = x, y = y })
		return true
	end
	return false
end

function UISystem:HandleRButtonUp(x, y)
	return false
end

function UISystem:HandleTextInput(text)
	print(text)
	-- 如果当前有选中焦点
	if self._sfc then
		-- 向焦点控件发送文本输入事件
		self._sfc:DispatchEvent({type = EventTypes.TEXTINPUT, target = self._sfc, text = text})
		return true
	end
	return false
end

-- 处理键盘按键按下事件
function UISystem:HandleKeydown(mod, sym, scancode)
	print(mod, sym, scancode)
	-- 如果当前有选中焦点
	if self._sfc then
		-- 向焦点控件发送键盘按键事件
		self._sfc:DispatchEvent({type = EventTypes.KEYDOWN, target = self._sfc, mod = mod, sym = sym, scancode = scancode})
		return true
	end
	return false
end

-- 处理键盘按键弹起事件
function UISystem:HandleMouseWheel(x, y)
	-- 判断当前滚动焦点控件是否存在
	if self._wfc then
		-- 如果y大于0，表示鼠标滚轮向上滚动。小于0表示向下滚动
		if y > 0 then
			self._wfc:DispatchEvent({type = EventTypes.MBUTTONWHEELUP, target = self._wfc})
		else
			self._wfc:DispatchEvent({type = EventTypes.MBUTTONWHEELDOWN, target = self._wfc})
		end
		return true
	end
end

-- 更新移动焦点控件
function UISystem:UpdateMoveFocus(x, y)
	-- 移动焦点控件
	local mfc = nil
	-- 移动焦点对话框
	local mfd = nil
	-- 滚动焦点控件
	local wfc = nil
	-- 重置滚动焦点
	self._wfc = nil
	-- 遍历所有层
	for layer_index, layer in ipairs(self.layers) do
		if layer._childs then
			-- 计算相对于层的x，y坐标
			local rel_x = x - layer._x
			local rel_y = y - layer._y
			-- 遍历层下面的所有对话框
			for dialog_index, dialog in ipairs(layer._childs) do
				-- 检测鼠标移动焦点
				wfc, mfc = dialog:PickUp(rel_x, rel_y)
				-- 如果滚动焦点控件不为空，那么就覆盖当前的
				if wfc then self._wfc = wfc end
				-- 如果有移动焦点控件，则跳出小循环
				if mfc then mfd = dialog break end
			end
			-- 如果移动焦点对话框，则跳出大循环
			if mfd then break end
		end
	end
	-- 如果计算得到的移动焦点控件就是当前的移动焦点控件
	if self._mfc == mfc then
		-- 如果移动焦点控件不为空，那么返回true
		if mfc then return true
		-- 如果移动焦点控件为空，那么返回false
		else return false end
	end
	-- 如果移动焦点控件部位不为空
	if self._mfc then
		-- 向移动焦点控件发送鼠标移出事件
		self._mfc:DispatchEvent({type = EventTypes.MOVEOUT, target = self._mfc, x = x, y = y})
	end
	
	-- 更新移动焦点控件和移动焦点对话框
	self._mfc = mfc
	self._mfd = mfd
	
	-- 如果更新后的移动焦点控件不为空，那么向移动焦点控件发送移入事件
	if mfc then
		mfc:DispatchEvent({type = EventTypes.MOVEIN, target = mfc, x = x, y = y})
		return true
	else
		return false
	end
end

-- 处理窗口大小变化
function UISystem:HandleWindowResized(width, height)
	self._window_width = width
	self._window_height = height

	for layer_index, layer in ipairs(self.layers) do
		layer:SetWidth(width)
		layer:SetHeight(height)
	end
end

g_UISystem = UISystem()
